'''
copyright: Copyright (C) 2015-2024, Wazuh Inc.

           Created by Wazuh, Inc. <info@wazuh.com>.

           This program is free software; you can redistribute it and/or modify it under the terms of GPLv2

type: integration

brief: Wazuh is able to detect vulnerabilities in the applications installed in agents using the Vulnerability Detector
       module. This software audit is performed through the integration of vulnerability feeds indexed by Redhat,
       Canonical, Debian, Amazon Linux and NVD Database.

components:
    - vulnerability_detector

suite: feeds

targets:
    - manager

daemons:
    - wazuh-modulesd
    - wazuh-db
    - wazuh-analysisd

os_platform:
    - linux

os_version:
    - Arch Linux
    - Amazon Linux 2022
    - Amazon Linux 2
    - Amazon Linux 1
    - CentOS 8
    - CentOS 7
    - Debian Buster
    - Red Hat 8
    - Ubuntu Trusty
    - Ubuntu Xenial
    - Ubuntu Bionic
    - Ubuntu Focal
    - Ubuntu Jammy
    - SUSE Linux Enterprise Desktop 15

references:
    - https://documentation.wazuh.com/current/user-manual/capabilities/vulnerability-detection/index.html

tags:
    - settings
    - vulnerability
    - vulnerability_detector
    - scan_results
'''
import pytest
from pathlib import Path

from wazuh_testing import FEEDS_PATH
from wazuh_testing.constants.daemons import ANALYSISD_DAEMON, MODULES_DAEMON, SYSCHECK_DAEMON
from wazuh_testing.constants.paths.logs import WAZUH_LOG_PATH
from wazuh_testing.utils.callbacks import generate_callback
from wazuh_testing.tools.monitors.file_monitor import FileMonitor
from wazuh_testing.utils.db_queries import cve_db
from wazuh_testing.utils.configuration import (load_configuration_template, get_test_cases_data,
                                               update_configuration_template)
from wazuh_testing.modules import vulnerability_detector as vd
from wazuh_testing.modules.modulesd.configuration import MODULESD_DEBUG
from wazuh_testing.modules.monitord.configuration import MONITORD_ROTATE_LOG
from wazuh_testing.modules.modulesd.vulnerability_detector import patterns as cb
from . import TEST_CASES_PATH, CONFIGURATIONS_PATH


pytest.skip("The tests will be deprecated, they test the old Vulnerability Detector.", allow_module_level=True)

pytestmark = [pytest.mark.server]

# Variables
local_internal_options = {MODULESD_DEBUG: '2', MONITORD_ROTATE_LOG: '0'}
daemons_handler_configuration = {'daemons': [ANALYSISD_DAEMON, MODULES_DAEMON, SYSCHECK_DAEMON]}

# Configuration and cases data
configurations_path = Path(CONFIGURATIONS_PATH, 'configuration_duplicate_feeds.yaml')
test_alert_vuln_removal_path = Path(TEST_CASES_PATH, 'cases_duplicate_feeds.yaml')

# Custom feeds path
custom_redhat_oval_feed_path = str(Path(FEEDS_PATH, 'redhat', vd.CUSTOM_REDHAT_OVAL_FEED))
custom_redhat_json_feed_path = str(Path(FEEDS_PATH, 'redhat', vd.CUSTOM_REDHAT_JSON_FEED))
custom_debian_oval_feed_path = str(Path(FEEDS_PATH, 'debian', vd.CUSTOM_DEBIAN_OVAL_FEED))
custom_debian_json_feed_path = str(Path(FEEDS_PATH, 'debian', vd.CUSTOM_DEBIAN_JSON_FEED))
custom_canonical_oval_feed_path = str(Path(FEEDS_PATH, 'canonical', vd.CUSTOM_CANONICAL_OVAL_FEED))
custom_alas_feed_path = str(Path(FEEDS_PATH, 'alas', vd.CUSTOM_ALAS_JSON_FEED))
custom_archlinux_feed_path = str(Path(FEEDS_PATH, 'arch', vd.CUSTOM_ARCHLINUX_JSON_FEED))
custom_msu_feed_path = str(Path(FEEDS_PATH, 'msu', vd.CUSTOM_MSU_JSON_FEED))
custom_suse_feed_path = str(Path(FEEDS_PATH, 'suse', vd.CUSTOM_SUSE_OVAL_FEED))

# Test configurations
configuration_parameters, configuration_metadata, test_case_ids = get_test_cases_data(
    test_alert_vuln_removal_path)
configurations = load_configuration_template(configurations_path, configuration_parameters,
                                             configuration_metadata)

# Set offline custom feeds configuration
to_modify = ['CUSTOM_REDHAT_OVAL_FEED_PATH', 'CUSTOM_REDHAT_JSON_FEED_PATH', 'CUSTOM_DEBIAN_OVAL_FEED_PATH',
             'CUSTOM_DEBIAN_JSON_FEED_PATH', 'CUSTOM_CANONICAL_OVAL_FEED_PATH', 'CUSTOM_ALAS_JSON_FEED_PATH',
             'CUSTOM_ARCHLINUX_JSON_FEED_PATH', 'CUSTOM_MSU_JSON_FEED_PATH', 'CUSTOM_SUSE_OVAL_FEED']
new_values = [custom_redhat_oval_feed_path, custom_redhat_json_feed_path, custom_debian_oval_feed_path,
              custom_debian_json_feed_path, custom_canonical_oval_feed_path, custom_alas_feed_path,
              custom_archlinux_feed_path, custom_msu_feed_path, custom_suse_feed_path]
configurations = update_configuration_template(configurations, to_modify, new_values)
configuration_metadata = update_configuration_template(configuration_metadata, to_modify, new_values)


def check_update_finish_logs(file_monitor=None, provider_name='', provider_json_name=''):
    """Check the provider database update finish event in ossec.log

    Args:
        file_monitor (FileMonitor): Log monitor.
        provider_name (str): Provider name of the downloaded feed.
        provider_json_name (str): Provider json name of the downloaded feed.

    Returns:
        int: number of vulnerabilities inserted
    """

    file_monitor.start(timeout=20, callback=generate_callback(regex=cb.FEED_UPDATE_FINISHED,
                                                              replacement={'provider_name': provider_name}))
    assert file_monitor.callback_result is not None, f"Could not find {cb.FEED_UPDATE_FINISHED} update starting log"

    if 'Red Hat Enterprise Linux 8' in provider_name:
        file_monitor.start(timeout=20, callback=generate_callback(regex=cb.FEED_UPDATE_FINISHED,
                                                                  replacement={'provider_name': provider_json_name}))
        assert file_monitor.callback_result is not None, f"Could not find {cb.FEED_UPDATE_FINISHED} update starting log"

    return cve_db.get_rows_number('VULNERABILITIES')


@pytest.mark.tier(level=2)
@pytest.mark.parametrize('test_configuration, test_metadata', zip(configurations, configuration_metadata),
                         ids=test_case_ids)
def test_duplicate_feeds(test_configuration, test_metadata, set_wazuh_configuration, truncate_monitored_files,
                         configure_local_internal_options, clean_cve_tables, daemons_handler):
    '''
    description: Check that the vulnerabilities are not repeated in the database when they are indexed from the feeds.

    test_phases:
        - setup:
            - Set a custom Wazuh configuration, with custom feeds.
            - Truncate wazuh logs.
            - Restart wazuh-modulesd daemon to apply configuration changes.
        - test:
            - Wait until feeds are downloaded and indexed in the DB.
            - Get the number of vulnerabilities inserted in the DB.
            - Wait until the next feeds download and indexation.
            - Check that the number of vulnerabilities info is the same than the before indexation.
        - teardown:
            - Truncate wazuh logs.
            - Restore initial configuration, both ossec.conf and local_internal_options.conf.

    wazuh_min_version: 4.4.0

    tier: 2

    parameters:
        - test_configuration:
            type: dict
            brief: Wazuh configuration data. Needed for set_wazuh_configuration fixture.
        - test_metadata:
            type: dict
            brief: Wazuh configuration metadata.
        - set_wazuh_configuration:
            type: fixture
            brief: Set the wazuh configuration according to the configuration data.
        - configure_local_internal_options:
            type: fixture
            brief: Set local_internal_options configuration.
        - truncate_monitored_files:
            type: fixture
            brief: Truncate all the log files and json alerts files before and after the test execution.
        - clean_cve_tables:
            type: fixture
            brief: Clean all CVE tables.
        - daemons_handler:
            type: fixture
            brief: Restart the wazuh-modulesd daemon.

    assertions:
        - Verify that the number of vulnerabilities inserted in the VULNERABILITIES table of CVE DB is not duplicated.

    input_description:
        - The `case_duplicate_feeds.yaml` file provides the module configuration for this test.

    expected_output:
        - 'The update of the <provider_name> feed finished successfully'
    '''
    file_monitor = FileMonitor(WAZUH_LOG_PATH)

    before_feeds_number = check_update_finish_logs(file_monitor=file_monitor,
                                                   provider_name=test_metadata['provider_name'],
                                                   provider_json_name=test_metadata['provider_json_name'])

    after_feeds_number = check_update_finish_logs(file_monitor=file_monitor,
                                                  provider_name=test_metadata['provider_name'],
                                                  provider_json_name=test_metadata['provider_json_name'])

    assert before_feeds_number == after_feeds_number
